﻿namespace EFS.RC.CCC.Application.EndPoints
{
	/// <summary>
	/// Manage our list of roles
	/// </summary>
	internal class List : EFS.Common.ISelfDescriptor
	{
		// sync access
		private object syncAccess = new object();

		/// <summary>
		/// EndPoints list
		/// </summary>
		private System.Collections.Generic.Dictionary<System.String, EndPoint> roles = new System.Collections.Generic.Dictionary<System.String, EndPoint>();

		/// <summary>
		/// Describe this object
		/// </summary>
		/// <returns></returns>
		public System.String Describe()
		{
			return "EFS.RC.CCC.Application.EndPoints.EndPoints";
		}

		/// <summary>
		/// Get agents
		/// </summary>
		public EFS.RC.CCC.Application.EndPoints.EndPoint GetApplicationEndPoint(System.String ownerUri)
		{
			lock (syncAccess)
			{
				return roles[ownerUri];
			}
		}

		/// <summary>
		/// Add new endPoint
		/// </summary>
		/// <param name="ownerUri"></param>
		public EndPoint Add(Microsoft.Rtc.Collaboration.ApplicationEndpointSettings applicationEndpointSettings)
		{
			EventLog.Log.LogInfo(System.String.Format("AddEndPoint {0}", applicationEndpointSettings.OwnerUri), this);

			// end oint
			EndPoint endPoint = null;

			// lock access to our list
			lock (syncAccess)
			{
				// check already in
				if (roles.ContainsKey(applicationEndpointSettings.OwnerUri))
				{
					throw new System.Exception(System.String.Format("EFS.RC.CCC.Application.EndPoints.EndPoints.Lis::AddEndPoint Already have a endPoint for {0}", applicationEndpointSettings.OwnerUri));
				}

				// check if we have an application setup
				EFS.RC.CCC.Deployment.Application.Model endPointDeployment = (new EFS.RC.CCC.Deployment.Application.List()).GetModel(applicationEndpointSettings.OwnerUri);

				// check if deployed
				if (null == endPointDeployment)
				{
					// no deplyment, add as defult, 
					endPoint = new Application.EndPoints.Default(applicationEndpointSettings);
				}
				else
				{
					// get run time
					switch (endPointDeployment.Runtime)
					{
						case "EFS.RC.CCC.Application.EndPoints.Models.Agent":
							{
								// make new
								endPoint = new EFS.RC.CCC.Application.EndPoints.Models.Agent(applicationEndpointSettings);
								break;
							}
						case "EFS.RC.CCC.Application.EndPoints.Models.Customer":
							{
								// make new
								endPoint = new EFS.RC.CCC.Application.EndPoints.Models.Customer(applicationEndpointSettings);
								break;
							}
						default:
							{
								// default end point, has no role
								throw new System.Exception(System.String.Format("EFS.RC.CCC.Application.EndPoints.EndPoints.Lis::AddEndPoint Runtime not available {0}", endPointDeployment.Runtime));
							}
					}
				}
				
				// add endPoint
				roles.Add(applicationEndpointSettings.OwnerUri, endPoint);
			}

			// done
			return endPoint;
		}

		/// <summary>
		/// Add new endPoint
		/// </summary>
		/// <param name="ownerUri"></param>
		public void ShutdownAll()
		{
			EventLog.Log.LogInfo("RemoveAll", this);

			// async list
			System.Collections.Generic.List<EFS.RC.Common.AsyncProcess> asyncProcesses = new System.Collections.Generic.List<Common.AsyncProcess>();

			// lock access to our list
			lock (syncAccess)
			{
				// each
				foreach(EndPoint endPoint in roles.Values)
				{
					// close it down
					asyncProcesses.Add(endPoint.BeginShutdown());
				}

				// clear
				roles.Clear();
			}

			// each
			foreach (EFS.RC.Common.AsyncProcess asyncProcess in asyncProcesses)
			{
				// wait 
				asyncProcess.WaitComplete();
			}
		}
	}
}
